commonlibsse_ng\re\i/
InputEvent.rs1use core::marker::PhantomData;
2use core::ptr::NonNull;
3
4use stdx::ptr::ConstNonNull;
5
6use crate::re::BSFixedString::BSFixedString;
7use crate::re::ButtonEvent::ButtonEvent;
8use crate::re::CharEvent::CharEvent;
9use crate::re::IDEvent::IDEvent;
10use crate::re::InputDevices::INPUT_DEVICE;
11use crate::re::MouseMoveEvent::MouseMoveEvent;
12use crate::re::ThumbstickEvent::ThumbstickEvent;
13use crate::re::offsets_rtti::RTTI_InputEvent;
14use crate::re::offsets_vtable::VTABLE_InputEvent;
15use crate::rel::id::VariantID;
16
17pub enum Event<'a> {
18 Button(&'a ButtonEvent),
19 MouseMove(&'a MouseMoveEvent),
20 Char(&'a CharEvent),
21 Thumbstick(&'a ThumbstickEvent),
22}
23
24#[commonlibsse_ng_derive_internal::to_bitflags]
25#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
26#[repr(u32)]
27pub enum INPUT_EVENT_TYPE {
28 Button = 0,
29 MouseMove,
30 Char,
31 Thumbstick,
32 DeviceConnect,
33 Kinect,
34}
35
36#[repr(C)]
37#[derive(Debug, PartialEq)]
38pub struct InputEvent {
39 pub vtable: *const InputEventVtbl, pub device: INPUT_DEVICE, pub eventType: INPUT_EVENT_TYPE, pub next: Option<NonNull<InputEvent>>, }
44const _: () = assert!(core::mem::size_of::<InputEvent>() == 0x18);
45
46impl InputEvent {
47 pub const RTTI: VariantID = RTTI_InputEvent;
49
50 pub const VTABLE: [VariantID; 1] = VTABLE_InputEvent;
52
53 pub const fn cast_to_event(&self) -> Option<Event> {
54 unsafe {
55 let this = self as *const Self;
56
57 Some(match self.eventType {
58 INPUT_EVENT_TYPE::Button => Event::Button(&*(this.cast())),
59 INPUT_EVENT_TYPE::MouseMove => Event::MouseMove(&*(this.cast())),
60 INPUT_EVENT_TYPE::Char => Event::Char(&*(this.cast())),
61 INPUT_EVENT_TYPE::Thumbstick => Event::Thumbstick(&*(this.cast())),
62 _ => return None,
63 })
64 }
65 }
66
67 pub fn as_id_event(&self) -> Option<&IDEvent> {
68 unsafe {
69 (self.vtable.as_ref()?.HasIDCode)(self)
70 .then(|| (self as *const Self).cast::<IDEvent>())
71 .and_then(|this| this.as_ref())
72 }
73 }
74
75 pub fn as_id_event_mut(&mut self) -> Option<&mut IDEvent> {
76 unsafe {
77 (self.vtable.as_ref()?.HasIDCode)(self)
78 .then(|| (self as *mut Self).cast::<IDEvent>())
79 .and_then(|this| this.as_mut())
80 }
81 }
82
83 #[inline]
84 pub const fn iter(&self) -> InputEventIterator {
85 InputEventIterator::new(self)
86 }
87}
88
89pub struct InputEventVtbl {
90 pub CxxDrop: unsafe extern "C" fn(this: *mut InputEvent), pub HasIDCode: unsafe extern "C" fn(this: *const InputEvent) -> bool, pub QUserEvent: unsafe extern "C" fn(this: *const InputEvent) -> &'static BSFixedString, }
94
95pub struct InputEventIterator<'a> {
97 current: Option<ConstNonNull<InputEvent>>,
98 marker: PhantomData<&'a InputEvent>,
99}
100impl<'a> InputEventIterator<'a> {
101 pub const fn new(current: &'a InputEvent) -> Self {
102 Self { current: Some(ConstNonNull::from_ref(current)), marker: PhantomData }
103 }
104}
105impl<'a> Iterator for InputEventIterator<'a> {
106 type Item = &'a InputEvent;
107
108 fn next(&mut self) -> Option<Self::Item> {
109 let current = self.current?;
110 let current_ref = unsafe { current.as_ref() };
111 self.current = current_ref.next.map(ConstNonNull::from_non_null);
112
113 Some(current_ref)
114 }
115}